package com.jl;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jl.annotation.JLTableName;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 连表查询
 */
@Component
public class JLJoin {

    private static Util.Mapper mapper;

    @Autowired(required = false)
    private void setBaseMapper(Util.Mapper mapper) {
        JLJoin.mapper = mapper;
    }

    //主表，列返回值主表是原样返回（驼峰），其他表则返回到对象
    public <T> Join from(Class<T> entity, JLLambda.JLFunction<T, ?>... jlFunction) {
        //主表语句
        String str = Util.getJoin(entity, Util.FROM);
        //显示字段
        String select = Util.getSelects(entity, true, jlFunction);
        //切换到连表对象
        return new Join(str, entity, select);
    }

    /**
     * 连表对象
     */
    @Getter(AccessLevel.PACKAGE)
    @Setter(AccessLevel.PACKAGE)
    public static class Join {
        //主表
        private String pstr;
        private Class<?> pentity;
        private String pselect;

        //连表语句
        private String str = "";

        public Join(String str, Class<?> entity, String select) {
            this.pstr = str;
            this.pentity = entity;
            this.pselect = select;
        }

        private <T> void set(Class<T> entity, String way, JLLambda.JLFunction<T, ?>... jlFunction) {
            str += Util.getJoin(entity, " " + way);
            pselect += "," + Util.getSelects(entity, false, jlFunction);
        }

        //inner join
        public <T> JoinOn inner(Class<T> entity, JLLambda.JLFunction<T, ?>... jlFunction) {
            set(entity, Util.JOIN, jlFunction);
            return new JoinOn(this);
        }

        //left join
        public <T> JoinOn left(Class<T> entity, JLLambda.JLFunction<T, ?>... jlFunction) {
            set(entity, Util.LEFT_JOIN, jlFunction);
            return new JoinOn(this);
        }

        //right join
        public <T> JoinOn right(Class<T> entity, JLLambda.JLFunction<T, ?>... jlFunction) {
            set(entity, Util.RIGHT_JOIN, jlFunction);
            return new JoinOn(this);
        }
    }

    /**
     * 连表对象带on
     */
    @Getter(AccessLevel.PACKAGE)
    @Setter(AccessLevel.PACKAGE)
    public static class JoinOn {
        //连表对象
        private Join join;

        //连表语句
        private String str = "";

        public JoinOn(Join Join) {
            this.join = Join;
        }

        private <T> void set(Class<T> entity, String way, JLLambda.JLFunction<T, ?>... jlFunction) {
            str += Util.getJoin(entity, " " + way);
            join.setPselect(join.getPselect() + "," + Util.getSelects(entity, false, jlFunction));
        }

        //inner join
        public <T> JoinOn inner(Class<T> entity, JLLambda.JLFunction<T, ?>... jlFunction) {
            set(entity, Util.JOIN, jlFunction);
            return this;
        }

        //left join
        public <T> JoinOn left(Class<T> entity, JLLambda.JLFunction<T, ?>... jlFunction) {
            set(entity, Util.LEFT_JOIN, jlFunction);
            return this;
        }

        //right join
        public <T> JoinOn right(Class<T> entity, JLLambda.JLFunction<T, ?>... jlFunction) {
            set(entity, Util.RIGHT_JOIN, jlFunction);
            return this;
        }

        //on切换到条件对象
        public <A, B> Where on(JLLambda.JLFunction<A, ?> jlFunction1, JLLambda.JLFunction<B, ?> jlFunction2) {
            return new Where(jlFunction1, jlFunction2, this);
        }
    }

    /**
     * 条件对象
     */
    @Getter(AccessLevel.PACKAGE)
    @Setter(AccessLevel.PACKAGE)
    public static class Where {
        //连表对象带on
        private JoinOn joinOn;

        //最后操作方法名
        private String last;

        //条件语句
        private String str = "";

        //on条件语句
        private String onStr = "";

        public <A, B> Where(JLLambda.JLFunction<A, ?> jlFunction1, JLLambda.JLFunction<B, ?> jlFunction2, JoinOn joinOn) {
            this.joinOn = joinOn;
            onStr += Util.getOn(jlFunction1, jlFunction2);
        }

        //连表条件
        public <A, B> Where on(JLLambda.JLFunction<A, ?> jlFunction1, JLLambda.JLFunction<B, ?> jlFunction2) {
            logicArithmeticOn();
            onStr += Util.getOn(jlFunction1, jlFunction2);
            last = "on";
            return this;
        }

        //连接符and
        public Where and() {
            str += " and ";
            last = "and";
            return this;
        }

        //连接符or
        public Where or() {
            str += " or ";
            last = "or";
            return this;
        }

        //连接符默认值处理
        private void logicArithmetic() {
            if (!"and".equals(last) && !"or".equals(last) && !"".equals(str)) {
                str += " and ";
            }
        }

        //连接符默认值处理
        private void logicArithmeticOn() {
            if (!"and".equals(last) && !"or".equals(last) && !"".equals(onStr)) {
                onStr += " and ";
            }
        }

        //运算符=
        public <T, R> Where eq(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.EQ);
            }
            last = "eq";
            return this;
        }

        //运算符<
        public <T, R> Where lt(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.LT);
            }
            last = "lt";
            return this;
        }

        //运算符>
        public <T, R> Where gt(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.GT);
            }
            last = "gt";
            return this;
        }

        //运算符<=
        public <T, R> Where le(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.LE);
            }
            last = "le";
            return this;
        }

        //运算符>=
        public <T, R> Where ge(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.GE);
            }
            last = "ge";
            return this;
        }

        //运算符 like
        public <T, R> Where like(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, "%" + value + "%", " " + Util.LIKE + " ");
            }
            last = "like";
            return this;
        }

        //运算符!=
        public <T, R> Where ne(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.NE);
            }
            last = "ne";
            return this;
        }

        //运算符in
        public <T, R> Where in(JLLambda.JLFunction<T, R> jlFunction, List value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, " " + Util.IN + " ");
            }
            last = "in";
            return this;
        }

        //运算符not in
        public <T, R> Where notIn(JLLambda.JLFunction<T, R> jlFunction, List value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, " " + Util.NOTIN + " ");
            }
            last = "notIn";
            return this;
        }

        //括号
        public Where brackets(Brackets brackets) {
            if (!StringUtils.isEmpty(brackets.getStr())) {
                logicArithmetic();
                str += "(" + brackets.getStr() + ")";
            }
            last = "brackets";
            return this;
        }

        //正序切换到排序对象
        public <T> Order asc(JLLambda.JLFunction<T, ?> jlFunction) {
            return new Order(jlFunction, Util.ASC, this, "");
        }

        //倒序切换到排序对象
        public <T> Order desc(JLLambda.JLFunction<T, ?> jlFunction) {
            return new Order(jlFunction, Util.DESC, this, "");
        }

        //分组切换到分组对象
        public <T> Group group(JLLambda.JLFunction<T, ?> jlFunction) {
            return new Group(jlFunction, this);
        }

        //数量
        public int count() {
            String sql = String.format("select count(*) as count %s where (%s)", joinOn.getJoin().getPstr() + joinOn.getJoin().getStr() + joinOn.getStr(), onStr);
            if (!"".equals(str)) {
                sql = String.format("%s and (%s)", sql, str);
            }
            return Util.exec(sql);
        }

        //对象
        public <T> T object(Class<T> result) {
            String sql = String.format("select %s %s where (%s)", joinOn.getJoin().getPselect(), joinOn.getJoin().getPstr() + joinOn.getJoin().getStr() + joinOn.getStr(), onStr);
            if (!"".equals(str)) {
                sql = String.format("%s and (%s)", sql, str);
            }
            List<T> list = Util.exec(sql, result);
            if (list.size() > 0) {
                return list.get(0);
            }
            return null;
        }

        //集合
        public <T> List<T> list(Class<T> result) {
            String sql = String.format("select %s %s where (%s)", joinOn.getJoin().getPselect(), joinOn.getJoin().getPstr() + joinOn.getJoin().getStr() + joinOn.getStr(), onStr);
            if (!"".equals(str)) {
                sql = String.format("%s and (%s)", sql, str);
            }
            return Util.exec(sql, result);
        }

        //分页
        public <T> IPage<T> page(Class<T> result, IPage<T> page) {
            //数量
            int count = count();
            //集合
            String sql = String.format("select %s %s where (%s)", joinOn.getJoin().getPselect(), joinOn.getJoin().getPstr() + joinOn.getJoin().getStr() + joinOn.getStr(), onStr);
            if (!"".equals(str)) {
                sql = String.format("%s and (%s)", sql, str);
            }
            sql = String.format("%s limit %d,%d", sql, (page.getCurrent() - 1) * page.getSize(), page.getSize());
            List<T> list = Util.exec(sql, result);
            page.setTotal(count);
            page.setRecords(list);
            return page;
        }
    }

    /**
     * 条件对象带括号
     */
    @Getter(AccessLevel.PACKAGE)
    @Setter(AccessLevel.PACKAGE)
    public static class Brackets {
        //条件语句
        private String str = "";

        //最后操作方法名
        private String last;

        //连接符默认值处理
        private void logicArithmetic() {
            if (!"and".equals(last) && !"or".equals(last) && !"".equals(str)) {
                str += " and ";
            }
        }

        //连接符and
        public Brackets and() {
            str += " and ";
            last = "and";
            return this;
        }

        //连接符or
        public Brackets or() {
            str += " or ";
            last = "or";
            return this;
        }

        //运算符=
        public <T, R> Brackets eq(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.EQ);
            }
            last = "eq";
            return this;
        }

        //运算符<
        public <T, R> Brackets lt(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.LT);
            }
            last = "lt";
            return this;
        }

        //运算符>
        public <T, R> Brackets gt(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.GT);
            }
            last = "gt";
            return this;
        }

        //运算符<=
        public <T, R> Brackets le(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.LE);
            }
            last = "le";
            return this;
        }

        //运算符>=
        public <T, R> Brackets ge(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.GE);
            }
            last = "ge";
            return this;
        }

        //运算符 like
        public <T, R> Brackets like(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, "%" + value + "%", " " + Util.LIKE + " ");
            }
            last = "like";
            return this;
        }

        //运算符!=
        public <T, R> Brackets ne(JLLambda.JLFunction<T, R> jlFunction, R value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, Util.NE);
            }
            last = "ne";
            return this;
        }

        //运算符in
        public <T> Brackets in(JLLambda.JLFunction<T, ?> jlFunction, List value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, " " + Util.IN + " ");
            }
            last = "in";
            return this;
        }

        //运算符not in
        public <T> Brackets notIn(JLLambda.JLFunction<T, ?> jlFunction, List value) {
            if (Util.valid(value)) {
                logicArithmetic();
                str += Util.getWhere(jlFunction, value, " " + Util.NOTIN + " ");
            }
            last = "notIn";
            return this;
        }
    }


    /**
     * 分组对象
     */
    @Getter(AccessLevel.PACKAGE)
    @Setter(AccessLevel.PACKAGE)
    public static class Group {
        //条件对象
        private Where where;

        //分组语句
        private String str = "";

        public <T> Group(JLLambda.JLFunction<T, ?> jlFunction, Where where) {
            str += Util.getGroup(jlFunction);
            where.getJoinOn().getJoin().setPselect(where.getJoinOn().getJoin().getPselect() + ",count(*) as count");
            this.where = where;
        }

        //正序切换到排序对象
        public <T> Order asc(JLLambda.JLFunction<T, ?> jlFunction) {
            return new Order(jlFunction, Util.ASC, where, str);
        }

        //倒序切换到排序对象
        public <T> Order desc(JLLambda.JLFunction<T, ?> jlFunction) {
            return new Order(jlFunction, Util.DESC, where, str);
        }

        //数量
        public int count() {
            String sql = String.format("select count(*) as count %s where (%s)", where.getJoinOn().getJoin().getPstr() + where.getJoinOn().getJoin().str + where.getJoinOn().getStr(), where.getOnStr());
            if (!"".equals(where.getStr())) {
                sql = String.format("%s and (%s)", sql, where.getStr());
            }
            return Util.exec(sql);
        }

        //对象
        public <T> T object(Class<T> result) {
            String sql = String.format("select %s %s where (%s)", where.getJoinOn().getJoin().getPselect(), where.getJoinOn().getJoin().getPstr() + where.getJoinOn().getJoin().str + where.getJoinOn().getStr(), where.getOnStr());
            if (!"".equals(where.getStr())) {
                sql = String.format("%s and (%s)", sql, where.getStr());
            }
            sql = String.format("%s group by %s", sql, str);
            List<T> list = Util.exec(sql, result);
            if (list.size() > 0) {
                return list.get(0);
            }
            return null;
        }

        //集合
        public <T> List<T> list(Class<T> result) {
            String sql = String.format("select %s %s where (%s)", where.getJoinOn().getJoin().getPselect(), where.getJoinOn().getJoin().getPstr() + where.getJoinOn().getJoin().str + where.getJoinOn().getStr(), where.getOnStr());
            if (!"".equals(where.getStr())) {
                sql = String.format("%s and (%s)", sql, where.getStr());
            }
            sql = String.format("%s group by %s", sql, str);
            return Util.exec(sql, result);
        }

        //分页
        public <T> IPage<T> page(Class<T> result, IPage<T> page) {
            //数量
            int count = count();
            //集合
            String sql = String.format("select %s %s where (%s)", where.getJoinOn().getJoin().getPselect(), where.getJoinOn().getJoin().getPstr() + where.getJoinOn().getJoin().str + where.getJoinOn().getStr(), where.getOnStr());
            if (!"".equals(where.getStr())) {
                sql = String.format("%s and (%s)", sql, where.getStr());
            }
            sql = String.format("%s group by %s", sql, str);
            sql = String.format("%s limit %d,%d", sql, (page.getCurrent() - 1) * page.getSize(), page.getSize());
            List<T> list = Util.exec(sql, result);
            page.setTotal(count);
            page.setRecords(list);
            return page;
        }
    }

    /**
     * 排序对象
     */
    @Getter(AccessLevel.PACKAGE)
    @Setter(AccessLevel.PACKAGE)
    public static class Order {
        //条件对象
        private Where where;

        //排序语句
        private String str = "";

        private String groupStr;

        //次数，用于拼接逗号
        private int num = 0;

        public <T> Order(JLLambda.JLFunction<T, ?> jlFunction, String by, Where where, String groupStr) {
            str += Util.getOrder(jlFunction, by);
            this.groupStr = groupStr;
            num++;
            this.where = where;
        }

        //正序
        public <T> Order asc(JLLambda.JLFunction<T, ?> jlFunction) {
            if (num > 0) {
                str += "," + Util.getOrder(jlFunction, Util.ASC);
            } else {
                str += Util.getOrder(jlFunction, Util.ASC);
            }
            num++;
            return this;
        }

        //倒序
        public <T> Order desc(JLLambda.JLFunction<T, ?> jlFunction) {
            if (num > 0) {
                str += "," + Util.getOrder(jlFunction, Util.DESC);
            } else {
                str += Util.getOrder(jlFunction, Util.DESC);
            }
            num++;
            return this;
        }

        //数量
        public int count() {
            String sql = String.format("select count(*) as count %s where (%s)", where.getJoinOn().getJoin().getPstr() + where.getJoinOn().getJoin().str + where.getJoinOn().getStr(), where.getOnStr());
            if (!"".equals(where.getStr())) {
                sql = String.format("%s and (%s)", sql, where.getStr());
            }
            return Util.exec(sql);
        }

        //对象
        public <T> T object(Class<T> result) {
            String sql = String.format("select %s %s where (%s)", where.getJoinOn().getJoin().getPselect(), where.getJoinOn().getJoin().getPstr() + where.getJoinOn().getJoin().str + where.getJoinOn().getStr(), where.getOnStr());
            if (!"".equals(where.getStr())) {
                sql = String.format("%s and (%s)", sql, where.getStr());
            }
            if (!"".equals(groupStr)) {
                sql = String.format("%s group by %s", sql, groupStr);
            }
            sql = String.format("%s order by %s", sql, str);
            List<T> list = Util.exec(sql, result);
            if (list.size() > 0) {
                return list.get(0);
            }
            return null;
        }

        //集合
        public <T> List<T> list(Class<T> result) {
            String sql = String.format("select %s %s where (%s)", where.getJoinOn().getJoin().getPselect(), where.getJoinOn().getJoin().getPstr() + where.getJoinOn().getJoin().str + where.getJoinOn().getStr(), where.getOnStr());
            if (!"".equals(where.getStr())) {
                sql = String.format("%s and (%s)", sql, where.getStr());
            }
            if (!"".equals(groupStr)) {
                sql = String.format("%s group by %s", sql, groupStr);
            }
            sql = String.format("%s order by %s", sql, str);
            return Util.exec(sql, result);
        }

        //分页
        public <T> IPage<T> page(Class<T> result, IPage<T> page) {
            //数量
            int count = count();
            //集合
            String sql = String.format("select %s %s where (%s)", where.getJoinOn().getJoin().getPselect(), where.getJoinOn().getJoin().getPstr() + where.getJoinOn().getJoin().str + where.getJoinOn().getStr(), where.getOnStr());
            if (!"".equals(where.getStr())) {
                sql = String.format("%s and (%s)", sql, where.getStr());
            }
            if (!"".equals(groupStr)) {
                sql = String.format("%s group by %s", sql, groupStr);
            }
            sql = String.format("%s order by %s", sql, str);
            sql = String.format("%s limit %d,%d", sql, (page.getCurrent() - 1) * page.getSize(), page.getSize());
            List<T> list = Util.exec(sql, result);
            page.setTotal(count);
            page.setRecords(list);
            return page;
        }

    }


    public static class Util {
        public final static String JOIN = "join", LEFT_JOIN = "left join", RIGHT_JOIN = "right join", FROM = "from";

        public final static String EQ = "=", LT = "<", GT = ">", LE = "<=", GE = ">=", LIKE = "like", NE = "!=", IN = "in", NOTIN = "not in";

        private final static String DESC = "desc", ASC = "asc";

        private static Pattern humpPattern = Pattern.compile("[A-Z]");

        /**
         * 连表
         *
         * @return
         */
        private static String getJoin(Class<?> entity, String way) {
            String tab = entity.getAnnotation(TableName.class).value();
            return way + " " + tab + " as " + tab;
        }

        /**
         * select
         *
         * @param entity
         * @return
         */
        private static <T> String getSelects(Class<T> entity, boolean master, JLLambda.JLFunction<T, ?>... jlFunction) {
            String select = "";
            String tab = entity.getAnnotation(TableName.class).value();
            List<JLTuple.Tuple3<String, Object, Class<?>>> tuple3s = JLReflect.PropertyReflect.getProperty(entity);
            for (JLTuple.Tuple3<String, Object, Class<?>> tuple3 : tuple3s) {
                String name = tuple3.getV1();
                boolean fal = true;
                for (JLLambda.JLFunction<T, ?> notColumn : jlFunction) {
                    if (name.equals(JLLambda.getProperty(notColumn))) {
                        fal = false;
                        break;
                    }
                }
                if (fal) {
                    select += master ? tab + "." + JLStringTools.humpToLine(name) + " as " + name + ","
                            : tab + "." + JLStringTools.humpToLine(name) + " as " + JLStringTools.toCamelCase(tab) + "$" + name + ",";
                }
            }
            select = select.substring(0, select.lastIndexOf(","));
            return select;
        }

        /**
         * 条件
         *
         * @return
         */
        private static <T, R> String getWhere(JLLambda.JLFunction<T, R> jlFunction, Object values, String arithmetic) {
            Class<T> entity = JLLambda.getClass(jlFunction);
            String property = JLLambda.getProperty(jlFunction);
            String sql = "";
            String tab = entity.getAnnotation(TableName.class).value();
            String value = "";
            if (arithmetic.equals(" " + IN + " ") || arithmetic.equals(" " + NOTIN + " ")) {
                List valueList = (List) values;
                value += "(";
                for (int i = 0; i < valueList.size(); i++) {
                    if (i < valueList.size() - 1) {
                        value += "'" + valueList.get(i) + "',";
                    } else {
                        value += "'" + valueList.get(i) + "'";
                    }
                }
                value += ")";
            } else {
                value = "'" + values + "'";
            }
            sql += tab + "." + JLStringTools.humpToLine(property) + arithmetic + value;
            return sql;
        }

        /**
         * on条件
         *
         * @return
         */
        private static <A, B> String getOn(JLLambda.JLFunction<A, ?> jlFunction1, JLLambda.JLFunction<B, ?> jlFunction2) {
            Class<A> entity1 = JLLambda.getClass(jlFunction1);
            Class<B> entity2 = JLLambda.getClass(jlFunction2);
            String property1 = JLLambda.getProperty(jlFunction1);
            String property2 = JLLambda.getProperty(jlFunction2);
            String tab1 = entity1.getAnnotation(TableName.class).value();
            String tab2 = entity2.getAnnotation(TableName.class).value();
            return tab1 + "." + JLStringTools.humpToLine(property1) + " " + EQ + " " + tab2 + "." + JLStringTools.humpToLine(property2);
        }

        /**
         * 分组
         *
         * @return
         */
        private static <A> String getGroup(JLLambda.JLFunction<A, ?> jlFunction) {
            Class<A> entity = JLLambda.getClass(jlFunction);
            String property = JLLambda.getProperty(jlFunction);
            String tab = entity.getAnnotation(TableName.class).value();
            String sql = tab + "." + JLStringTools.humpToLine(property);
            return sql;
        }

        /**
         * 排序
         *
         * @return
         */
        private static <A> String getOrder(JLLambda.JLFunction<A, ?> jlFunction, String by) {
            Class<A> entity = JLLambda.getClass(jlFunction);
            String property = JLLambda.getProperty(jlFunction);
            String tab = entity.getAnnotation(TableName.class).value();
            String sql = tab + "." + JLStringTools.humpToLine(property) + " " + by;
            return sql;
        }

        /**
         * 执行sql
         *
         * @param sql
         * @param result
         * @param <T>
         * @return
         */
        private static <T> List<T> exec(String sql, Class<T> result) {
            List<Map> exec = mapper.exec(sql);
            List results = new ArrayList();
            for (Map map : exec) {
                try {
                    Object o = map2Object(map, result);
                    results.add(o);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return results;
        }

        /**
         * 执行sql
         *
         * @param sql
         * @return
         */
        private static Integer exec(String sql) {
            List<Map> exec = mapper.exec(sql);
            return Integer.parseInt(exec.get(0).get("count").toString());
        }

        /**
         * Map转成实体对象
         *
         * @param map
         * @param clazz
         * @param <T>
         * @return
         */
        public static <T> T map2Object(Map<String, Object> map, Class<T> clazz) throws Exception {
            Object obj = clazz.newInstance();
            //查找变量名
            Map<String, JLTuple.Tuple3<String, Object, Class<?>>> tableName = new HashMap<>();
            Object finalObj = obj;
            map.forEach((s, o) -> {
                if (s.indexOf("$") != -1) {
                    String tableNames = s.substring(0, s.indexOf("$"));
                    JLTuple.Tuple3<String, Object, Class<?>> tuple3 = JLReflect.PropertyReflect.getProperty(finalObj, tableNames);
                    if (tuple3 != null && tableName.get(tableNames) == null) {
                        tableName.put(tableNames, tuple3);
                    }
                }
            });
            //查找注解
            List<JLTuple.Tuple4<String, Object, Class<?>, JLTableName>> tuple4s = JLReflect.PropertyReflect.getProperty(obj, JLTableName.class);
            for (JLTuple.Tuple4<String, Object, Class<?>, JLTableName> tuple4 : tuple4s) {
                JLTableName annotation = tuple4.getV4();
                String tableNames = JLStringTools.toCamelCase(annotation.value());
                if (tableName.get(tableNames) == null) {
                    String name = tuple4.getV1();
                    JLTuple.Tuple3<String, Object, Class<?>> tuple3 = JLReflect.PropertyReflect.getProperty(finalObj, name);
                    tableName.put(tableNames, tuple3);
                }
            }
            /**
             * 处理主表属性
             */
            List<JLTuple.Tuple3<String, Object, Class<?>>> tuple3sp = JLReflect.PropertyReflect.getProperty(finalObj);
            for (JLTuple.Tuple3<String, Object, Class<?>> tuple3p : tuple3sp) {
                String name = tuple3p.getV1();
                if (tableName.get(name) != null) {
                    continue;
                }
                Object value = map.get(name);
                JLReflect.PropertyReflect.setPropertyValue(finalObj, name, value);
            }
            /**
             * 处理关联对象
             */
            tableName.forEach((s, tuple3) -> {
                Class<?> join = tuple3.getV3();
                try {
                    Object o = join.newInstance();
                    List<JLTuple.Tuple3<String, Object, Class<?>>> tuple3ss = JLReflect.PropertyReflect.getProperty(o);
                    for (JLTuple.Tuple3<String, Object, Class<?>> tuple3s : tuple3ss) {
                        String name = tuple3s.getV1();
                        Object value = map.get(s + "$" + name);
                        JLReflect.PropertyReflect.setPropertyValue(o, name, value);
                    }
                    //tuple3.getV1()可能为变量名，可能为注解值
                    JLReflect.PropertyReflect.setPropertyValue(finalObj, tuple3.getV1(), o);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            return (T) obj;
        }

        /**
         * 条件有效判断
         *
         * @param value
         * @return
         */
        public static boolean valid(Object value) {
            if (value == null) {
                return false;
            }
            if (value instanceof String) {
                if ("".equals(value.toString().trim())) {
                    return false;
                }
            }
            if (value instanceof List) {
                if (((List) value).size() == 0) {
                    return false;
                }
            }
            return true;
        }

        public interface Mapper {
            @Select("${sql}")
            List<Map> exec(@Param("sql") String sql);
        }
    }
}
